/**
 * 
 */
package callchain;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import soot.Scene;
import soot.SceneTransformer;
import soot.SootMethod;
import soot.jimple.toolkits.callgraph.CallGraph;
import callchain.lightcallgraph.LightCallGraph;
import callchain.lightcallgraph.SootCallGraphNodeRepo;

/**
 * This transformer is designed to take effect in 
 * the cg pack to obtain the call graph and construct
 * the interesting call chains from the starting 
 * method to the ending method.
 * 
 * @author Cheng Zhang
 * @since 2.0
 */
public class CallChainTransformer extends SceneTransformer {

	/* (non-Javadoc)
	 * @see soot.SceneTransformer#internalTransform(java.lang.String, java.util.Map)
	 */
	@Override
	protected void internalTransform(String phaseName, Map options) {
		Integer startIndex = null;
		Integer endIndex = null;
		
		CallGraph cg = Scene.v().getCallGraph();
		LightCallGraph lcg = new LightCallGraph();
		System.err.println(cg.size());
		
		
		Iterator edges = cg.listener();
		while(edges.hasNext()){
			soot.jimple.toolkits.callgraph.Edge currentEdge =
				(soot.jimple.toolkits.callgraph.Edge)edges.next();
			SootMethod srcMethod = currentEdge.src();
			SootMethod tgtMethod = currentEdge.tgt();
//			System.out.println(srcMethod.getDeclaringClass() + "::" + srcMethod.getName() + 
//					           "==" + currentEdge.kind() + "==>" + tgtMethod.getDeclaringClass() + "::" + tgtMethod.getName());
			if(   srcMethod.getDeclaringClass().isApplicationClass() 
			   && tgtMethod.getDeclaringClass().isApplicationClass()){ // we only focus on the interesting application classes.
				System.out.println(srcMethod.getDeclaringClass() + "::" + srcMethod.getName() + 
		           "==" + currentEdge.kind() + "==>" + tgtMethod.getDeclaringClass() + "::" + tgtMethod.getName());
				SootCallGraphNodeRepo.indexCallGraphNode(srcMethod);
				SootCallGraphNodeRepo.indexCallGraphNode(tgtMethod);
				Integer srcNodeIndex = SootCallGraphNodeRepo.getNodeIndex(srcMethod);
				Integer tgtNodeIndex = SootCallGraphNodeRepo.getNodeIndex(tgtMethod);
				lcg.addArc(srcNodeIndex, tgtNodeIndex);
				
				/*
				if( srcMethod.getSignature().equals("<antlr.Tool: void main(java.lang.String[])>") ){
					startIndex = srcNodeIndex;
				}
				if( tgtMethod.getSignature().equals("<antlr.ANTLRParser: void grammar()>")){
					endIndex = tgtNodeIndex;
				}
				*/
			}
		}
		

		SootCallGraphNodeRepo.printRepository();
		SootCallGraphNodeRepo.storeRepository("index_2_methodsig_antlr.txt");
		lcg.storeGraph("callgraph_antlr.txt");
		
/*		CallChainFinder chainFinder = new CallChainFinder(lcg);
		System.err.println("Start Index: " + startIndex);
		System.err.println("End Index: " + endIndex);
		chainFinder.findAllCallChains(startIndex, endIndex, new ArrayList<Integer>());
		System.err.println(chainFinder.getAllCallChains());*/
	}

}
